using System;
using System.Collections.Generic;
using MetaObjects.Contracts;

namespace MetaObjects.Core
{
	public class EntityMapper<TSource, TTarget> : MapperBase<TSource, TTarget>
	{
		private readonly Func<TTarget> _ctor;
		private readonly List<Action<TSource, TTarget>> _actions;

		public EntityMapper(Func<TSource, TTarget> map) : base(map) { }

		public EntityMapper(IMetaEntity source, IMetaEntity target)
		{
			_ctor = () => (TTarget)target.Factory();
			_actions = new List<Action<TSource, TTarget>>();
			foreach (var metaField in source.MetaFields)
			{
				var name = metaField.InternalName;
				if (target.MetaFields.Contains(name))
				{
					var targetField = target.MetaFields[name];
					IMetaField sourceField = metaField;
					Action<TSource, TTarget> action = (s, t) => targetField.SetField(t, sourceField.GetField(s));
					_actions.Add(action);
				}
			}
		}

		protected override TTarget MapInternal(TSource source)
		{
			TTarget target = _ctor();
			foreach (Action<TSource, TTarget> action in _actions)
			{
				action(source, target);
			}
			return target;
		}
	}
}